package org.lds.simple.disruptor.sequence;

import org.lds.simple.disruptor.sequence.value.RightValuePadding;
import org.lds.simple.disruptor.sequence.value.Value;
import org.lds.simple.disruptor.util.Util;
import sun.misc.Unsafe;

public class Sequence extends RightValuePadding {
    private static final long INIT_VALUE = -1;
    private static final Unsafe unsafe = Util.getUnsafe();
    private static final long valueOffset;

    static {
        try {
            valueOffset = unsafe.objectFieldOffset(Value.class.getDeclaredField("value"));
        } catch (Exception ex) {
            throw new Error(ex);
        }
    }

    public Sequence() {
        this(INIT_VALUE);
    }

    public Sequence(long initValue) {
        set(initValue);
    }

    public final long get() {
        return value;
    }

    public final void set(long newValue) {
        unsafe.putOrderedLong(this, valueOffset, newValue);
    }

    public final long getAndSet(long newValue) {
        return unsafe.getAndSetLong(this, valueOffset, newValue);
    }

    public final boolean compareAndSet(long expect, long update) {
        return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
    }

    public final long getAndIncrement() {
        return unsafe.getAndAddLong(this, valueOffset, 1L);
    }

    public final long incrementAndGet() {
        return unsafe.getAndAddLong(this, valueOffset, 1L) + 1L;
    }

}
